package com.black.utils.encrypt.md5;

import lombok.extern.slf4j.Slf4j;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Utility class for MD5 encryption.
 * MD5加密的工具类。
 *
 * @author ylx
 */
@Slf4j
public class MD5Util {
    // Global array of hexadecimal digits
    // 全局数组，存放16进制字符
    private final static String[] strDigits = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};


    /**
     * Convert a byte to a hexadecimal string.
     * 将字节转换为16进制字符串。
     *
     * @param bByte The byte to convert.
     *              要转换的字节。
     * @return The hexadecimal string representation of the byte.
     * 字节的16进制字符串表示。
     */
    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return strDigits[iD1] + strDigits[iD2];
    }


    /**
     * Convert a byte array to a hexadecimal string.
     * 将字节数组转换为16进制字符串。
     *
     * @param bByte The byte array to convert.
     *              要转换的字节数组。
     * @return The hexadecimal string representation of the byte array.
     * 字节数组的16进制字符串表示。
     */
    private static String byteToString(byte[] bByte) {
        StringBuilder builder = new StringBuilder();
        for (byte b : bByte) {
            builder.append(byteToArrayString(b));
        }
        return builder.toString();
    }

    /**
     * Get the MD5 hash of a string.
     * 获取字符串的MD5哈希值。
     *
     * @param strObj The string to hash.
     *               要进行哈希处理的字符串。
     * @return The MD5 hash of the string.
     * 字符串的MD5哈希值。
     */
    public static String getMD5Code(String strObj) {
        return getMD5CodeByBytes(strObj.getBytes());
    }

    /**
     * Get the MD5 hash of a byte array.
     * 获取字节数组的MD5哈希值。
     *
     * @param bytes The byte array to hash.
     *              要进行哈希处理的字节数组。
     * @return The MD5 hash of the byte array.
     * 字节数组的MD5哈希值。
     */
    public static String getMD5CodeByBytes(byte[] bytes) {
        String resultString = null;
        try {
            resultString = new String(bytes);
            MessageDigest md = MessageDigest.getInstance("MD5");
            // md.digest() 该函数返回值为存放哈希值结果的byte数组
            resultString = byteToString(md.digest(bytes));
        } catch (NoSuchAlgorithmException ex) {
            log.error(ex.getMessage());
        }
        return resultString;
    }


    /**
     * Verify the MD5 hash of a string.
     * 验证字符串的MD5哈希值。
     *
     * @param srcStr       The string to verify.
     *                     要进行验证的字符串。
     * @param md5HexString The MD5 hash of the string to verify.
     *                     要验证的字符串的MD5哈希值。
     * @return True if the MD5 hash matches, false otherwise.
     * 如果MD5哈希值匹配，则返回true，否则返回false。
     */
    public static boolean verify(String srcStr, String md5HexString) {
        return getMD5Code(srcStr).equals(md5HexString);
    }
}